#ifndef _WX_MEMORYH__
#define _WX_MEMORYH__

#include "wx/defs.h"
#include "wx/string.h"
#include "wx/msgout.h"

#if (defined(__WXDEBUG__) && wxUSE_MEMORY_TRACING) || wxUSE_DEBUG_CONTEXT

#include <stddef.h>

typedef unsigned int wxMarkerType;

class wxMemStruct {
    friend class wxDebugContext; // access to the m_next pointer for list traversal.
  public:
  public:
    int AssertList();
    size_t RequestSize() { return m_reqSize; }
    wxMarkerType Marker() { return m_firstMarker; }
    inline void SetDeleted();
    inline int IsDeleted();
    int Append();
    int Unlink();
    int AssertIt();
    int ValidateNode();
    int CheckBlock();
    int CheckAllPrevious();
    void PrintNode();
    void ErrorMsg( const char * );
    void ErrorMsg();
    inline void *GetActualData( void ) const { return m_actualData; }
    void Dump( void );
  public:
    wxMarkerType        m_firstMarker;
    wxChar* m_fileName;
    int m_lineNum;
    size_t m_reqSize;
    wxMarkerType m_id;
    wxMemStruct * m_prev;
    wxMemStruct * m_next;
    void * m_actualData;
    bool m_isObject;
};


typedef void ( wxMemStruct::*PmSFV )();

class wxDebugContext {
  protected:
    // Used to set alignment for markers.
    static size_t CalcAlignment();
    static size_t GetPadding( const size_t size ) ;
    static void TraverseList( PmSFV, wxMemStruct *from = NULL );
    static int debugLevel;
    static bool debugOn;
    static int m_balign;            // byte alignment
    static int m_balignmask;        // mask for performing byte alignment
  public:
    static wxMemStruct *checkPoint;
    wxDebugContext( void );
    ~wxDebugContext( void );
    static int GetLevel( void ) { return debugLevel; }
    static void SetLevel( int level ) { debugLevel = level; }
    static bool GetDebugMode( void ) { return debugOn; }
    static void SetDebugMode( bool flag ) { debugOn = flag; }
    static void SetCheckpoint( bool all = false );
    static wxMemStruct *GetCheckpoint( void ) { return checkPoint; }
    static size_t PaddedSize( const size_t reqSize );
    static size_t TotSize( const size_t reqSize );
    static char * StructPos( const char * buf );
    static char * MidMarkerPos( const char * buf );
    static char * CallerMemPos( const char * buf );
    static char * EndMarkerPos( const char * buf, const size_t size );
    static char * StartPos( const char * caller );
    static wxMemStruct * GetHead() { return m_head; }
    static wxMemStruct * GetTail() { return m_tail; }
    static wxMemStruct * SetHead( wxMemStruct * st ) { return ( m_head = st ); }
    static wxMemStruct * SetTail( wxMemStruct * st ) { return ( m_tail = st ); }
    static bool GetCheckPrevious() { return m_checkPrevious; }
    static void SetCheckPrevious( bool value ) { m_checkPrevious = value; }
    static int Check( bool checkAll = false );
    static bool PrintList( void );
    static bool Dump( void );
    static bool PrintStatistics( bool detailed = true );
    static bool PrintClasses( void );
    static int CountObjectsLeft( bool sinceCheckpoint = false );
    static void OutputDumpLine( const wxChar *szFormat, ... );
  private:
    static wxMemStruct* m_head;
    static wxMemStruct* m_tail;
    static bool m_checkPrevious;
};

class wxDebugContextDumpDelayCounter {
  public:
    wxDebugContextDumpDelayCounter() {
      sm_count++;
    }

    ~wxDebugContextDumpDelayCounter() {
      sm_count--;
      if( !sm_count ) {
        DoDump();
      }
    }
  private:
    void DoDump();
    static int sm_count;
};

static wxDebugContextDumpDelayCounter wxDebugContextDumpDelayCounter_File;
#define WXDEBUG_DUMPDELAYCOUNTER \
  static wxDebugContextDumpDelayCounter wxDebugContextDumpDelayCounter_Extra;

void wxTrace( const wxChar *fmt ... ) ATTRIBUTE_PRINTF_1;
void wxTraceLevel( int level, const wxChar *fmt ... ) ATTRIBUTE_PRINTF_2;

#define WXTRACE wxTrace
#define WXTRACELEVEL wxTraceLevel

#else

#define WXDEBUG_DUMPDELAYCOUNTER


#define wxTrace(fmt)
#define wxTraceLevel(l, fmt)

#define WXTRACE true ? (void)0 : wxTrace
#define WXTRACELEVEL true ? (void)0 : wxTraceLevel

#endif

#endif
